13 内存管理
独享内存空间的原理
内存都被分成一块一块儿的编好了号这样一个地址,通过这个地址定位到物理内存 的位置。
物理地址对于进程不可见,不能直接访问物理地址。操作系统会给进程分配一个虚拟地址。所有进程看到的这个地址都是一样的,里面的内存都是从 0 开始编号。
指令写入的地址是虚拟地址,操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来。当程序要访问虚拟地址,由内核的数据结构进行转换,转换成不同的物理地址,不同的进程运行的时候,写入的是不同的物理地址。
规划虚拟地址空间
- 物理内存的管理
- 虚拟地址的管理
- 虚拟地址和物理地址如何映射
程序在使用内存时的几种方式:
- 代码;
- 全局变量;
- 常量字符串;
- 函数栈;
- 堆;
- 对 glibc 的调用,glibc 的代码是以 so 文件的形式存在的,也需要放在内存里面。
内核部分需要分配的内存:
- 内核的代码;
- 内核中全局变量;
- 每个进程的 task_struct;
- 每个进程的内核栈;
- 动态分配的内存;
- 虚拟地址到物理地址的映射表。
虚拟内存中,放内核的部分称为内核空间,放进程的部分称为用户空间。
内存空间从最低位开始:
- Text Segment 存放二进制可执行代码;
- Data Segment 存放静态常量;
- BSS Segment 存放未初始化的静态变量;
- 堆(Heap)段,用来动态分配内存区域;
- Memory Mapping Segment,用来把文件映射进内存(动态链接库);
- 栈(Stack)地址段,存放主线程的函 数调用的函数栈;
内存映射
分段
段表,段描述符表(segment descriptors)在全局描述符表 GDT(Global Descriptor Table)里,通过 GDT_ENTRY_INIT 初始化段描述符表里面的表项。
分页(Paging)
把内存分成一块一块大小相同的页,内存页面长时间不用,可以暂时写到硬盘上,称为换出。一旦需要再加载进来,叫做换入。可以扩大可用物理内存的大小,提高物理内存的利用率。